#!/usr/bin/perl -w


# Helper script to strip unused parts out of crossrpms's rpm.specs
#
# Usage: specstrip < infile > outfile


# Copyright (C) 2005,2006,2010	Ralf Corsépius, Ulm, Germany,
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# For a copy of the GNU General Public License, visit
# http://www.gnu.org or write to the Free Software Foundation, Inc.,
# 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.

# $Id: specstrip,v 1.10 2010/04/06 11:31:11 ralf Exp $

use Getopt::Long;

use strict;

my $newlib = 0;
my $infos = 0;
my $prefix = '/usr';

my $verbose = 0;
my @languages = ();
my %options = ();

GetOptions(
  \%options,
  'prefix=s' => \$prefix,
  'enable-infos' => sub { $options{infos} = 1 },
  'disable-infos' => sub { $options{infos} = 0 },
  'newlib!',
  'languages=s' => \@languages,
  'verbose+' => \$verbose
) or die( "failed to GetOptions" );

if ( !defined($options{infos}) )
{ # User did not override, use defaults
  if ( $prefix =~ m/^\/usr$/ ) {
    $infos = 0;
  } elsif ( $prefix =~ m/^\/usr\/local$/ ) {
    $infos = 0;
  } else {
    $infos = 1;
  }
} else {
  $infos = int($options{infos});
}

if ( defined($options{newlib}) )
{
  $newlib = $options{newlib};
} else {
  $newlib = 0;
}

if ( $verbose ) {
  print STDERR "INFOS  : $infos\n";
  print STDERR "PREFIX : $prefix\n";
}

my %langs;

foreach ( split(/,/,join(',',@languages)) ){
  $langs{$_} = 1;
}

my @npatterns = (
  "(\"%\{_prefix\}\" (!=|==) \"/usr\")",

  "(%build_cxx)",
  "(%build_gnat)",
  "(%build_objc)",
  "(%build_gcj)",
  "(%build_libgcj)",
  "(%build_fortran)",
  "(%build_newlib)",
  "(%build_infos)"
);

my @ppatterns = (
);

push @ppatterns,  "(\"%\{_prefix\}\" " . (("$prefix" eq '/usr') ? '!=' : '==' ) . " \"/usr\")";

push @ppatterns, "(%build_gnat "   . ( ($langs{gnat}) ? "==" : "!=" ) . " 0)";
push @ppatterns, "(%build_cxx "    . ( ($langs{cxx}) ? "==" : "!=" ) . " 0)";
push @ppatterns, "(%build_objc "   . ( ($langs{objc}) ? "==" : "!=" ) . " 0)";
push @ppatterns, "(%build_gcj "    . ( ($langs{gcj}) ? "==" : "!=" ) . " 0)";
push @ppatterns, "(%build_libgcj " . ( ($langs{libgcj}) ? "==" : "!=" ) . " 0)";
push @ppatterns, "(%build_fortran "    . ( ($langs{fortran}) ? "==" : "!=" ) . " 0)";

push @ppatterns, "(%build_newlib " . ( ($newlib) ? "==" : "!=" ) . " 0)";
push @ppatterns, "(%build_infos " . ( ($infos) ? "==" : "!=" ) . " 0)";

my $npat = join('|',@npatterns);
my $ppat = join('|',@ppatterns);

if ( $verbose > 1 ) {
  print STDERR "PPAT: ", $ppat, "\n"; 
  print STDERR "NPAT: ", $npat, "\n";
}

my @buffer0 = <> ;

my @buffer2 ;

my @condstack ;

@condstack = ();
push @condstack,'<>';
foreach (@buffer0)
{
   chomp $_;
   if ( /^%if(os|)\s+(.*)$/ )
   {
     push @condstack,"<$2>";
     if ( $condstack[$#condstack] =~ m/$npat/ ) {
       # transform unary conditionals into binary conditionals
       if ( $condstack[$#condstack] =~/.*<(%[a-zA-Z_0-9]+)>.*/ ) {
         $condstack[$#condstack] = "<$1 != 0>";
       }
     } else {
       push @buffer2, { state => join('',@condstack), line => "$_" };
     }
   } elsif ( /^%else.*$/ )
   {
     my %ops = (
         "!=" => "==",
         "==" => "!="
       );

     if ( $condstack[$#condstack] =~/.*<(.*) (!=|==) (.*)>.*/ ) {
       $condstack[$#condstack] = "<$1 " .  $ops{$2} . " $3>";
       if ( $condstack[$#condstack] =~ m/$npat/ ) {
       } else {
         push @buffer2, { state => join('',@condstack), line => "$_" };
       }
     } else {
         push @buffer2, { state => join('',@condstack), line => "$_" };
     }
   } elsif ( /^%endif.*$/ )
   {
     if ( $condstack[$#condstack] =~ m/$npat/ ) {
     } else {
       push @buffer2, { state => join('',@condstack), line => "$_" };
     }
     pop @condstack;
   } else {
     push @buffer2, { state => join('',@condstack), line => "$_" };
   }
}

my @buffer3;
foreach my $i ( @buffer2 )
{
  print STDERR "STATE:", $i->{state}, " LINE:", $i->{line}, "\n" if $verbose > 1;
  if ( $i->{state} =~ m/($ppat)/ ) {
  } else {
          push @buffer3, $i->{line};
  }
}

#foreach my $line ( @buffer3 )
#{
#  print STDERR "L:<$line>\n";
#}

my @buffer4;
@condstack = ();
push @condstack, "<>";
foreach my $line ( @buffer3 )
{
#  print STDERR "READ:{", $line, "}\n";
  if ( $line =~/^%if\s+"([a-zA-Z_0-9\.\-]+)"\s+==\s+"([a-zA-Z_0-9\.\-]+)"\s*$/ )
  {
    if ( "$1" eq "$2" ) {
      push @condstack,"<TRUE:$1 == $2>";
    } else {
      push @condstack,"<FALSE:$1 == $2>";
    }
  } elsif ( $line =~/^%if\s+"([a-zA-Z_0-9\.\-]+)"\s+!=\s+"([a-zA-Z_0-9\.\-]+)"\s*$/ )
  {
    if ( "$1" ne "$2" ) {
      push @condstack,"<TRUE:$1 != $2>";
    } else {
      push @condstack,"<FALSE:$1 != $2>";
    }
  } elsif ( $line =~/^%if\s+(.*)\s*$/ )
  {
    my $exp = $1;
    if ( $condstack[$#condstack] =~ m/<FALSE:.*\s*>$/ ) {
      push @condstack,"<FALSE:$exp>";
    } else {
      push @condstack,"<IFOT:$exp>";
      push @buffer4, "$line\n";
    }
  } elsif ( $line =~/^%if((os|narch)\s+.*)\s*$/ )
  {
    my $exp = $1;
    if ( $condstack[$#condstack] =~ m/<FALSE:(.*)\s*>$/ ) {
      push @condstack,"<FALSE:$exp>";
    } else {
      push @condstack,"<IFOT:$exp>";
      push @buffer4, "$line\n";
    }
  } elsif ( $line =~ /^%else\s*$/ ) {
    if ( $condstack[$#condstack] =~ m/<TRUE:(.*)\s*>$/ ) {
      $condstack[$#condstack] = "<FALSE:$1>";
    } elsif ( $condstack[$#condstack] =~ m/<FALSE:(.*)\s*>$/ ) {
      $condstack[$#condstack] = "<TRUE:$1>";
    } else {
      push @buffer4, "$line\n";
    }
  } elsif ( $line =~ /^%endif\s*$/ ) {

    if ( $condstack[$#condstack] =~ m/<TRUE:.*>$/ ) {
#    print STDERR "ENDIF: TRUE\n";
    } elsif ( $condstack[$#condstack] =~ m/<FALSE:.*>$/ ) {
#    print STDERR "ENDIF: FALSE\n";
    } else {
      push @buffer4, "%endif\n";
    }
#    print STDERR "POP: $line\n";
    pop @condstack;
  } else {
#  print STDERR "CATCH $condstack[$#condstack]:$line\n";
    if ( $condstack[$#condstack] =~ m/<TRUE:.*>$/ ) {
      push @buffer4, "$line\n";
    } elsif ( $condstack[$#condstack] =~ m/<FALSE:.*>$/ ) {
    } else {
      push @buffer4, "$line\n";
    }
  }

#  print STDERR @condstack, "LINE: $line\n";
}

print STDOUT @buffer4;
